package FIT::Fixture::Row;

use FIT::Class;
use FIT::TypeAdapter;
use aliased 'FIT::TypeAdapter::Null';
use FIT::Document::Transformer;
use aliased 'FIT::Util::Wrapper';
use aliased 'FIT::Util::MultiLevelIndex' => 'Index';

extends 'FIT::Fixture::Column';

has matched => (is => 'rw', isa => 'Any', default => undef);
has index   => (is => 'rw', isa => Index, handles => [qw(find surplus)]);

sub query { () } # template method

before do_rows => sub { # execute query and save index
    my $row = shift;
    local $_;
    $self->index(Index->new(
        keys  => [$row->fit_input_columns],
        query => [map { Wrapper->new(wrapped => $_) } $self->query],
    ));
};

sub execute { # find object in query using it's keys, mark row accordingly
    my $row = shift;
    return if $row->has_errors;
    inner();
    $self->matched( $self->find($self) );
    transform { $self->matched? Right: Wrong note is 'missing' } $row;
}

sub make_adapter {
    my $cell    = shift;
    my $is_out  = $cell->fit_is_output_cell;
    my $matched = $self->matched;
    return Null->new if $is_out && !$matched; # ignore output column on no match

    my @args = $cell->fit_is_output_cell?
        (adaptee => $self->matched, type_from => $self):
        (adaptee => $self);
    return adapt(@args, name => $cell->column_heading);
}

after do_rows => sub { # add surplus
    my $row       = shift;
    my $table     = $row->table;
    my @headings  = $table->column_headings;
    for my $surplus ( $self->surplus ) {
        my ($row) = transform
            { AddRows rows are [[ map { '' } @headings ]] } $table;
        adapt(
            adaptee   => $surplus,
            type_from => $self,
            name      => $_->column_heading
        )->handle_blank($_)
            for $row->cells; # paint surplus into cells
        transform { Wrong note is 'surplus' } $row;
    }
};

